<?php

namespace App\Models;

use App\Models\Kms\User\KmsUser;
use Closure;
use Guanguans\Notify\Proxy\HigherOrderTapProxy;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Collection;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

abstract class BaseModel extends Model
{
    const CREATED_AT = 'createdAt';
    const UPDATED_AT = 'updatedAt';
    const DELETED_AT = 'deletedAt';

    protected $dateFormat = 'U';

    const DELETE_YES = 1;
    const DELETE_NO  = 0;

    const DEFAULT_YES = 1;
    const DEFAULT_NO  = 0;

    /**
     * 新增记录
     */
    public function addData()
    {
        $arr = [];
        foreach ($this->fillable as $field) {
            if ($this->$field === null) {
                continue;
            }

            $arr[$field] = $this->$field;
        }

        return self::query()->create($arr);
    }

    /**
     * 批量新增
     * @param Collection $data
     * @param bool $kfUid
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function batchAddData(Collection $data, bool $kfUid = true): bool
    {
        $now = time();

        if (!$kfUid) {
            $operateUid = 0;
        } else {
            try {
                $operateUid = (int)optional(getRmsUserInfoByAuth())->id;
            } catch (\Exception $e) {
                $operateUid = 0;
            }

        }

        return self::query()->insert($data->map(function ($item) use ($now, $operateUid, $kfUid) {
            $item['createdAt'] = $item['updatedAt'] = $now;

            if ($kfUid) {
                $item['createdByUid'] = $item['updatedByUid'] = $operateUid;
            }

            return $item;
        })->toArray());
    }

    /**
     * 将Query转换成待参数的sql
     * @param \Illuminate\Database\Query\Builder $query
     * @return string
     */
    public static function toSqlWithParam(Builder $query): string
    {
        $rawSql = str_replace('?', '"%s"', $query->toSql());
        return sprintf($rawSql, ...$query->getBindings());
    }

    /**
     * @param array $conditions
     * @param array|Closure $init
     * @param Closure|null $afterCreateClosure
     * @return HigherOrderTapProxy|Builder|Model|\Illuminate\Support\HigherOrderTapProxy|mixed|object|null
     */
    public static function customFirstOrCreate(array $conditions, $init, Closure $afterCreateClosure = null)
    {
        if (!is_null($instance = self::query()->where($conditions)->first())) {
            return $instance;
        }

        return tap(static::query()->newModelInstance(array_merge($conditions,
            $init instanceof Closure ? $init() : $init)), function ($instance) use ($afterCreateClosure) {
            $instance->save();

            if ($afterCreateClosure) {
                $afterCreateClosure($instance);
            }
        });
    }

    /**
     * @param string $key
     * @return bool
     */
    public function hasAttribute(string $key): bool
    {
        return array_key_exists($key, $this->attributes);
    }

    /**
     * @return HasOne
     */
    public function createdByUidRel(): HasOne
    {
        return $this->hasOne(KmsUser::class, "rmsUserId", "createdByUid");
    }

    /**
     * @return HasOne
     */
    public function updatedByUidRel(): HasOne
    {
        return $this->hasOne(KmsUser::class, "rmsUserId", "updatedByUid");
    }
}
